<template>
  <div class="video-box" @contextmenu="contextmenuRight">
    <video
      muted
      autoplay
      :id="index"
      :class="showInfo ? 'video' : 'videos'"
      @dblclick="handleDblClick"

    ></video>
    <el-button
      class="reconnect-btn"
      :style="{ display: showUrl === url ? 'block' : 'none' }"
      @click="reconnect"
      >重新连接</el-button
    >
  </div>
</template>

<script setup>
import flvjs from 'flv.js'
import { ref, onUnmounted, onMounted, toRefs, watch } from 'vue'
const player = ref(null)
const showInfo = ref(true)
const showUrl = ref(null)
const props = defineProps({
  url: {
    type: String,
    default: ''
  },
  index: {
    type: String
  },
  isError: {
    type: Boolean,
    default: false
  }
})
const { url, index, isError } = toRefs(props)
onMounted(() => {
  // 初始化websocket 视频
  initVideo()
})
const initVideo = () => {
  showUrl.value = null
  if (flvjs.isSupported()) {
    var videoElement = document.getElementById(index.value)
    player.value = flvjs.createPlayer(
      {
        type: 'flv',
        isLive: true,
        url: url.value,
        hasAudio: false // 关闭视频音频
      },
      {
        enableWorker: false, //不启用分离线程
        enableStashBuffer: false, //关闭IO隐藏缓冲区
        reuseRedirectedURL: true, //重用301/302重定向url，用于随后的请求，如查找、重新连接等。
        autoCleanupSourceBuffer: true //自动清除缓存
      }
    )
    player.value.attachMediaElement(videoElement)
    if (url.value !== '' && url.value !== null) {
      player.value.load()
      player.value.play()
    }

    player.value.on(flvjs.Events.ERROR, function(event, data) {
      switch (data.type) {
        case flvjs.ErrorTypes.NETWORK_ERROR:
          reconnect()
          break;
        case flvjs.ErrorTypes.MEDIA_ERROR:
          reconnect()
          break;
        default:
          // 处理其他未分类的错误
          console.error('其他错误:', data.details);
          if (data.details === 'flvjs.ErrorDetails.FLV_FORMAT_ERROR') {
            reconnect()
            return
          } else if (data.details === 'flvjs.ErrorDetails.FLV_UNRECOVERABLE_ERROR') {
            reconnect()
            return
          }
          reconnect()
          // 根据实际情况添加更多case来处理其他错误详情
          break;
      }
    })

    // 获取时间跟不上帧数的问题
    setInterval(() => {
      if (videoElement.buffered.length) {
        let end = videoElement.buffered.end(0) //获取当前buffered值
        let diff = end - videoElement.currentTime //获取buffered与currentTime的差值
        if (diff >= 0.5) {
          //如果差值大于等于0.5 手动跳帧 这里可根据自身需求来定
          videoElement.currentTime = videoElement.buffered.end(0) //手动跳帧
        }
      }
    }, 2000) //2000毫秒执行一次
    //定时方法是为了用户离开页面视频是实时播放的,暂停按钮无用
    setInterval(function () {
      // console.log(videoElement.buffered,"idididid");
      if (videoElement.buffered.length > 0) {
        const end = videoElement.buffered.end(0) // 视频结尾时间
        const current = videoElement.currentTime //  视频当前时间
        const diff = end - current // 相差时间
        // console.log(diff);
        const diffCritical = 4 // 这里设定了超过4秒以上就进行跳转
        const diffSpeedUp = 1 // 这里设置了超过1秒以上则进行视频加速播放
        const maxPlaybackRate = 4 // 自定义设置允许的最大播放速度
        let playbackRate = 1.0 // 播放速度
        if (diff > diffCritical) {
          //  this.flvPlayer.load();
          // console.log("相差超过4秒，进行跳转");
          videoElement.currentTime = end - 1.5
          playbackRate = Math.max(1, Math.min(diffCritical, 16))
        } else if (diff > diffSpeedUp) {
          // console.log("相差超过1秒，进行加速");
          playbackRate = Math.max(1, Math.min(diff, maxPlaybackRate, 16))
        }
        videoElement.playbackRate = playbackRate
        if (videoElement && videoElement.paused) {
          videoElement.play()
        }
      }
    }, 1000)
  }
}
const destoryVideo = () => {
  if (player.value) {
    player.value.pause()
    player.value.unload()
    player.value.detachMediaElement()
    player.value.destroy()
    player.value = null
  }
}
const handleDblClick = () => {
  showInfo.value = !showInfo.value
  if (!showInfo.value) {
    ElMessage.warning('双击鼠标左键关闭全屏')
    player.value.play()
  } else {
    player.value.pause()
  }
}
// 鼠标右击事件重连视频
const contextmenuRight = (event) => {
  event.preventDefault()
  if (showUrl.value) {
    showUrl.value = null
  } else {
    showUrl.value = url.value
  }
}
const reconnect = () => {
  if (player.value) {
    player.value.pause()
    player.value.unload()
    player.value.detachMediaElement()
    player.value.destroy()
    player.value = null
    initVideo()
  }
}
//组件卸载前清楚视频数据
onUnmounted(() => {
  destoryVideo()
})

watch(isError, (newValues, oldValues) => {
  //报警的时候关闭全屏
  if (newValues && !showInfo) {
    handleDblClick()
  }
})
</script>
<style scoped lang="scss">
.video-box {
  width: 100%;
  height: 100%;
}
.video {
  width: 100%;
  height: 100%;
  cursor: pointer;
  object-fit: fill;
}
.reconnect-btn {
  position: absolute;
  right: 50%;
  top: 50%;
  transform: translate(50%, 45%);
  cursor: pointer;
}
.videos {
  width: 100%;
  height: 100%;
  position: fixed;
  cursor: pointer;
  object-fit: fill;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #999;
  z-index: 7;
}
</style>
